package com.probiz.estore.content.service.impl;


import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import com.probiz.estore.Constants;
import com.probiz.estore.catalog.dao.ContentCategoryDao;
import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.common.model.catalog.ContentCategory;
import com.probiz.estore.common.model.content.Content;
import com.probiz.estore.common.model.content.ContentMedia;
import com.probiz.estore.common.model.content.ContentStat;
import com.probiz.estore.content.dao.ContentDao;
import com.probiz.estore.content.dao.ContentStatDao;
import com.probiz.estore.content.model.ContentFullyModel;
import com.probiz.estore.content.model.ContentSearchCriteria;
import com.probiz.estore.content.service.ContentManager;
import com.probiz.estore.content.service.ContentMediaManager;
import com.probiz.estore.content.service.RelatedContentManager;
import com.probiz.estore.core.search.SearchCriteria;
import com.probiz.estore.core.service.impl.GenericManagerImpl;
import com.probiz.estore.core.util.ContextUtil;
import com.probiz.estore.solrsearch.service.SolrSearchService;


/**
 * Manager implementation for Content, responsible for business processing, and communicate between web and persistence layer.
 */
public class ContentManagerImpl extends GenericManagerImpl<Content> implements ContentManager {

    private ContentDao contentDao = null;
    private ContentCategoryDao contentCategoryDao = null;
    private ContentMediaManager contentMediaManager = null;
    private RelatedContentManager relatedContentManager = null;
    private ContentStatDao contentStatDao = null;
    
    /**
     * @param contentDao the contentDao to set
     */
    public void setContentDao(ContentDao contentDao) {
        this.contentDao = contentDao;
    }


    public void setContentCategoryDao(ContentCategoryDao contentCategoryDao) {
        this.contentCategoryDao = contentCategoryDao;
    }


    public void setContentMediaManager(ContentMediaManager contentMediaManager) {
		this.contentMediaManager = contentMediaManager;
	}
    


	public void setRelatedContentManager(RelatedContentManager relatedContentManager) {
		this.relatedContentManager = relatedContentManager;
	}
	

	public void setContentStatDao(ContentStatDao contentStatDao) {
		this.contentStatDao = contentStatDao;
	}


	/*
      * (non-Javadoc)
      *
      * @see com.probiz.estore.core.service.impl.GenericManagerImpl#init()
      */
    @Override
    protected void initManager() {
        dao = contentDao;
    }

    /*
      * (non-Javadoc)
      *
      * @see com.probiz.estore.core.service.impl.GenericManagerImpl#onDelete(java.lang.Object)
      */
    @Override
    protected void preDelete(Content entity) {

    }

    /*
      * (non-Javadoc)
      *
      * @see com.probiz.estore.core.service.impl.GenericManagerImpl#onSave(java.lang.Object)
      */
    @Override
    protected void preSave(Content entity) {

    }

    /**
     *
     */
    public List<Content> searchByCriteria(ContentSearchCriteria contentSearchCriteria, SearchCriteria searchCriteria) {
        return contentDao.searchByCriteria(contentSearchCriteria, searchCriteria);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#searchByCriteriaForController(com.probiz.estore.content.model.ContentSearchCriteria, com.probiz.estore.core.search.SearchCriteria)
      */
    public List<Content> searchByCriteriaForController(ContentSearchCriteria contentSearchCriteria, SearchCriteria searchCriteria) {
        if (searchCriteria.getPageNo() < 1)  //如果是翻页过前，就拿第一页就可以。
        {
            searchCriteria.changePaging(1, searchCriteria.getPageSize());
        }
        List<Content> result = searchByCriteria(contentSearchCriteria, searchCriteria);
        if (result == null || result.size() == 0) {
            if (searchCriteria.getPageNo() > searchCriteria.getTotalPageCount()) //如果是翻页前，就拿最后一页就可以。
            {
                searchCriteria.changePaging(searchCriteria.getTotalPageCount(), searchCriteria.getPageSize());
                result = searchByCriteria(contentSearchCriteria, searchCriteria);
            }
        }
        return result;
    }
    
   /*
    * (non-Javadoc)
    * @see com.probiz.estore.content.service.ContentManager#getContentList(com.probiz.estore.content.model.ContentSearchCriteria, int, int)
    */
    public List<Content> getContentList(final ContentSearchCriteria contentSearchCriteria,final int firstResult, final int maxResults){
    	return contentDao.getContentList(contentSearchCriteria, firstResult, maxResults);
    }

  
    public Map<String, Object> saveFully(ContentFullyModel model) {
    	Map<String, Object> returnMsgs = new HashMap<String, Object>();
    	Content content = model.getContent();
        boolean isNew = (content.getContentId() == null);
        Short oldStatus = content.getStatus();
        setExpiredTime(content);
        setStatus(content);
        contentDao.save(content);
        updateContentCategoryItemCount(oldStatus, content.getStatus(), content.getCategoryId(), isNew, false);
        
        // start:保存媒体信息
		List<String> newMediaIds = contentMediaManager.saveMediasFromArrays(content, model.getMediaIds(), model.getMediaUrls(), model.getMediaTypes(), model.getMediaDescs());
		returnMsgs.put("newMediaIds", newMediaIds);
		//保存主图
		if(!ArrayUtils.isEmpty(model.getMediaUrls())){
			for(int i=0; i< model.getMediaTypes().length;i++){
				if(model.getMediaTypes()[i].equals(ContentMedia.TYPE_IMAGE.toString())){
					content.setImageUrl(model.getMediaUrls()[i]);
					break;
				}
			}
		}else{
			//清空冗余
			content.setImageUrl("");
		}
		// end:保存媒体信息
		
		// start:保存统计信息
		ContentStat contentStat = content.getContentStat();
		if (contentStat == null) {
			contentStat = new ContentStat();
			contentStat.setViewCount(0);
		}
		contentStatDao.save(contentStat);
		content.setContentStat(contentStat);
		// end: 保存统计信息
		
		// start:关联商品
		relatedContentManager.saveRelatedContentsFromArrays(content, null, model.getRelatedTypeIds(), model.getRelatedContentIds());
		// end:关联商品
		
		contentDao.save(content);
		return returnMsgs;
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#deleteFully(com.probiz.estore.content.model.Content)
      */
    public void deleteFully(Content content) {
        updateContentCategoryItemCount(content.getStatus(), content.getStatus(), content.getCategoryId(), false, true);
        contentDao.delete(content);
        if (null != content.getContentStat())	contentStatDao.delete(content.getContentStat());
        if(ConfigUtil.getInstance().isOpenFulltextSearch()){
        	//删除solr索引
        	SolrSearchService  solrSearchService = (SolrSearchService)ContextUtil.getInstance().getSpringBeanById("solrSearchService");
        	solrSearchService.deleteIndex(content.getContentId()+"c");
        }
    }

    /**
     * 根据产品获得前台uri
     *
     * @param content 内容
     */
    private void setExpiredTime(Content content) {
        if (content.getValidPeriod().shortValue() == Content.VALID_PERIOD_NEVERINVALID
                .shortValue()) {
            content.setExpiredTime(null);
        } else {
            content.setExpiredTime(calExpiredTime(content.getPublishTime(),
                    content.getValidPeriod()));
        }
    }

    /**
     * 计算过期时间
     *
     * @param shelveTime  上架时间
     * @param validPeriod 有效期
     * @return 过期时间
     */
    private Date calExpiredTime(Date shelveTime, Short validPeriod) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(shelveTime);
        Calendar expiredTime = (Calendar) calendar.clone();
        expiredTime.set(Calendar.DAY_OF_YEAR, expiredTime
                .get(Calendar.DAY_OF_YEAR)
                + Content.validPeriodMap.get(validPeriod));
        return expiredTime.getTime();
    }

    /**
     * 设置文章状态
     *
     * @param content 文章
     */
    private void setStatus(Content content) {
        if (content.getIsShow() == null || content.getIsShow().shortValue() == Constants.FLAG_FALSE.shortValue()) {
            content.setStatus(Content.STATUS_INACTIVE);
        } else {
            Calendar calendar = Calendar.getInstance();
            //稍稍延长一点时间
            calendar.add(Calendar.SECOND, 10);
            Date now = calendar.getTime();
            if (now.getTime() <= content.getPublishTime().getTime()) {
                content.setStatus(Content.STATUS_WAITING_FOR_PUBLISH);
            } else if ((now.getTime() > content.getPublishTime().getTime()) && (content.getExpiredTime() == null || now.getTime() < content.getExpiredTime().getTime())) {
                content.setStatus(Content.STATUS_PUBLISHED);
            } else {
                content.setStatus(Content.STATUS_INACTIVE);
            }
        }
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#updateExpired(com.probiz.estore.content.model.Content)
      */
    public void updateExpired(Content content) {
        Short oldStatus = content.getStatus();
        content.setPublishTime(new Date());
        setExpiredTime(content);
        setStatus(content);
        contentDao.save(content);
        updateContentCategoryItemCount(oldStatus, content.getStatus(), content.getCategoryId(), false, false);
    }

    /**
     * 更新有效期
     *
     * @param contentId 文章id
     */
    public void updateExpired(Integer contentId) {
        Content content = this.getById(contentId);
        updateExpired(content);
    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.content.service.ContentManager#updateStatField(java.lang.Integer, java.lang.String, java.lang.Integer)
     */
    public void updateStatField(final Integer contentStatId,final String fieldName,final Integer count){
    	contentDao.updateStatField(contentStatId, fieldName, count);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#countContentByCategoryId(java.lang.Integer)
      */
    public Integer countContentByCategoryId(Integer categoryId) {
        return contentDao.countContentByCategoryId(categoryId);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#countContentIncludeAllByCategory(com.probiz.estore.catalog.model.ContentCategory)
      */
    public Integer countContentIncludeAllByCategory(ContentCategory contentCategory) {
        return contentDao.countContentIncludeAllByCategory(contentCategory);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#countActiveContentIncludeAllByCategory(com.probiz.estore.catalog.model.ContentCategory)
      */
    public Integer countActiveContentIncludeAllByCategory(ContentCategory contentCategory) {
        return contentDao.countActiveContentIncludeAllByCategory(contentCategory);
    }


    /**
     * 更新内容目录的文章数量,包括其上面的祖辈目录
     *
     * @param categoryId      产品目录id
     * @param itemCount       要改变的数量，可正可负
     * @param activeItemCount 要改变的激活数量，可正可负
     */
    private void updateContentCategoryItemCount(Integer categoryId, Integer itemCount, Integer activeItemCount) {
        ContentCategory contentCategory = contentCategoryDao.getById(categoryId);
        do {
            contentCategory.setItemCount(contentCategory.getItemCount() + itemCount);
            contentCategory.setActiveItemCount(contentCategory.getActiveItemCount() + activeItemCount);
            contentCategoryDao.save(contentCategory);
            contentCategory = contentCategory.getParent();
        } while (null != contentCategory);

    }

    /**
     * 更新内容目录的文章数量,包括其上面的祖辈目录
     *
     * @param oldStatus  原状态
     * @param currStatus 当前状态
     * @param categoryId 目录id
     * @param isNew      是否新目录
     * @param isDelete   是否已删除
     */
    private void updateContentCategoryItemCount(Short oldStatus, Short currStatus, Integer categoryId, boolean isNew, boolean isDelete) {
        if (isNew) {
            if (currStatus.shortValue() == Content.STATUS_PUBLISHED.shortValue()) {
                updateContentCategoryItemCount(categoryId, 1, 1);
            } else {
                updateContentCategoryItemCount(categoryId, 1, 0);
            }
        } else if (isDelete) {
            if (currStatus.shortValue() == Content.STATUS_PUBLISHED.shortValue()) {
                updateContentCategoryItemCount(categoryId, -1, -1);
            } else {
                updateContentCategoryItemCount(categoryId, -1, 0);
            }
        } else {
            if (oldStatus.shortValue() != currStatus.shortValue()) {
                if (currStatus.shortValue() == Content.STATUS_PUBLISHED.shortValue()) {
                    updateContentCategoryItemCount(categoryId, 0, 1);
                } else if (oldStatus.shortValue() == Content.STATUS_PUBLISHED.shortValue()) {
                    updateContentCategoryItemCount(categoryId, 0, -1);
                }
            }
        }
    }

   

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#getRecommendedContents(java.lang.Integer, int)
      */
    public List<Content> getRecommendedContents(final Integer categoryId, final int size) {
        final ContentCategory category = contentCategoryDao.getById(categoryId);
        return contentDao.getRecommendedContents(category, size);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#getNewestContents(com.probiz.estore.catalog.model.ContentCategory, int)
      */
    public List<Content> getNewestContents(final Integer categoryId, final int size) {
        final ContentCategory category = contentCategoryDao.getById(categoryId);
        return contentDao.getNewestContents(category, size);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#getRelatedContents(java.lang.Integer, int)
      */
    public List<Content> getRelatedContents(final Integer contentId, final int size) {
        return contentDao.getRelatedContents(contentId, size);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#getContentIdByUri(java.lang.String)
      */
    public Integer getContentIdByUri(String uri) {
        String contentId = uri.substring(uri.lastIndexOf("item"), uri
                .lastIndexOf("."));
        contentId = contentId.substring("item".length());
        return Integer.valueOf(contentId);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.content.service.ContentManager#getUriByContent(com.probiz.estore.content.model.Content)
      */
    public String getUriByContent(Content content) {
        StringBuffer url = new StringBuffer();
        url.append("/cms");
        for (ContentCategory contentCategory : contentCategoryDao.getNavigationCategories(content.getCategoryId())) {
        	url.append("-");
            url.append(contentCategory.getCategoryCode());
        }
        url.append("/item");
        url.append(content.getContentId().toString());
		url.append(".html");
		return url.toString();
	}

}
